package org.liaohailong.library.log;

import android.app.Application;
import android.os.Process;
import android.util.Log;

import androidx.annotation.NonNull;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

/**
 * create by liaohailong
 * time 2022/8/24 15:22
 * desc: 全app应用层 log 日志打印
 */
public class Logcat {

    private static Application sApp;
    private static LogConfig sLogConfig = null;
    private static LogFileWriter sLogFileWriter = null;
    // 时间 进程id-线程id/包名 log等级/tag: 信息
    private static final String LOG_MSG_FORMAT = "%s %d-%d/%s %s/%s: %s";
    private static final SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");

    public static void init(@NonNull Application app,
                            @NonNull LogConfig config) {
        sApp = app;
        sLogConfig = config;
        sLogFileWriter = new LogFileWriter(config.getFilepath());
    }

    public static Logcat obtain(@NonNull Object obj) {
        String simpleName = obj.getClass().getSimpleName();
        int hashCode = obj.hashCode();
        String tag = simpleName + "@" + hashCode;
        return obtain(tag);
    }

    public static Logcat obtain(@NonNull Class<?> clz) {
        String tag = clz.getSimpleName();
        return obtain(tag);
    }

    public static Logcat obtain(@NonNull String tag) {
        return new Logcat(tag);
    }

    @NonNull
    private final String tag;

    private Logcat(@NonNull String tag) {
        this.tag = tag;
    }

    public void v(@NonNull String msg, Object... args) {
        println(Log.VERBOSE, msg, args);
    }

    public void d(@NonNull String msg, Object... args) {
        println(Log.DEBUG, msg, args);
    }

    public void i(@NonNull String msg, Object... args) {
        println(Log.INFO, msg, args);
    }

    public void w(@NonNull String msg, Object... args) {
        println(Log.WARN, msg, args);
    }

    public void e(@NonNull String msg, Object... args) {
        println(Log.ERROR, msg, args);
    }

    public void exception(@NonNull Throwable tr) {
        String ex = Log.getStackTraceString(tr);
        e(ex);
    }


    private void println(int level, String msg, Object... args) {
        if (sLogConfig == null) {
            throw new IllegalStateException("log config is null, should call init() first");
        }
        // log 等级过滤
        if (level < sLogConfig.getLevel()) return;

        String format = String.format(msg, args);
        Log.println(level, tag, format);

        // 本地log文件缓存
        if (sLogFileWriter != null) {

            // 时间 进程id-线程id/包名 log等级/tag: 信息
            String logLine = String.format(
                    Locale.ENGLISH,
                    LOG_MSG_FORMAT,
                    sDateFormat.format(new Date()),
                    Process.myPid(),
                    Process.myTid(),
                    sApp.getPackageName(),
                    getLevel(level),
                    tag,
                    format
            );

            sLogFileWriter.write(logLine);
        }
    }

    private String getLevel(int level) {
        String result = "?";

        switch (level) {
            case Log.VERBOSE:
                result = "V";
                break;
            case Log.DEBUG:
                result = "D";
                break;
            case Log.INFO:
                result = "I";
                break;
            case Log.WARN:
                result = "W";
                break;
            case Log.ERROR:
                result = "E";
                break;
        }

        return result;
    }
}
